﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Unity;
using StockholmsStad.Windows.UI.Infrastructure.ValidationRules;
using StockholmsStad.Windows.UI.Modules.Couple.Properties;

namespace StockholmsStad.Windows.UI.Modules.Couple.Models
{
    public class CoupleDetailPresentationModel : INotifyPropertyChanged, IDataErrorInfo
    {
        private readonly IDictionary<string, string> errors = new Dictionary<string, string>();

        private static IEventAggregator eventAggregator;
        private static readonly IUnityContainer container = new UnityContainer();

        public event EventHandler<DataEventArgs<CoupleDetailPresentationModel>> Saved;
        public event EventHandler<DataEventArgs<CoupleDetailPresentationModel>> Added;
        public event EventHandler<DataEventArgs<CoupleDetailPresentationModel>> Searched;
        public event EventHandler<DataEventArgs<CoupleDetailPresentationModel>> Cancelled;
        public DelegateCommand<object> CancelCommand { get; private set; }
        public DelegateCommand<object> SaveCommand { get; private set; }
        public DelegateCommand<object> SearchCommand { get; private set; }
        public DelegateCommand<object> AddCommand { get; private set; }

        #region Contructor
        public CoupleDetailPresentationModel()
        {
            container.RegisterType<IEventAggregator, EventAggregator>();
            eventAggregator = container.Resolve<IEventAggregator>();

            AddCommand = new DelegateCommand<object>(Add);
            SaveCommand = new DelegateCommand<object>(Save, CanSave);
            SearchCommand = new DelegateCommand<object>(Search);
            CancelCommand = new DelegateCommand<object>(Cancel);
            PropertyChanged += OnPropertyChangedEvent;
            Validate();
        }
        #endregion

        public string HeaderInfo
        {
            get { return HeaderNames.Couple; }
        }

        #region Properties

        public int? TicketId { get; set; }

        private bool isInChangeMode;
        public bool IsInChangeMode
        {
            get { return isInChangeMode; }
            set { isInChangeMode = value; }
        }

        #region Person1 properties

        private string person1FirstNames;
        public string Person1FirstNames
        {
            get
            {
                return person1FirstNames;
            }
            set
            {
                if (!value.Equals(person1FirstNames))
                {
                    person1FirstNames = value;
                    if (Person1IsContact)
                        ContactPersonFirstName = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1FirstNames"));
                }
            }
        }

        private string person1LastName;
        public string Person1LastName
        {
            get
            {
                return person1LastName;
            }
            set
            {
                if (!value.Equals(person1LastName))
                {
                    person1LastName = value;
                    if(Person1IsContact)
                        ContactPersonLastName = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1LastName"));
                }
            }
        }

        private string person1PersonalNumber;
        public string Person1PersonalNumber
        {
            get
            {
                return person1PersonalNumber;
            }
            set
            {
                if (!value.Equals(person1PersonalNumber))
                {
                    person1PersonalNumber = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1PersonalNumber"));
                }
            }
        }

        private bool person1SwedishNationality;
        public bool Person1SwedishNationality
        {
            get
            {
                return person1SwedishNationality;
            }
            set
            {
                if (!value.Equals(person1SwedishNationality))
                {
                    person1SwedishNationality = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1SwedishNationality"));
                }
            }
        }

        private string person1Nationality;
        public string Person1Nationality
        {
            get
            {
                return person1Nationality;
            }
            set
            {
                if (!value.Equals(person1Nationality))
                {
                    person1Nationality = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1Nationality"));
                }
            }
        }

        private bool person1ProtectedIdentity = false;
        public bool Person1ProtectedIdentity
        {
            get
            {
                return person1ProtectedIdentity;
            }
            set
            {
                if (!value.Equals(person1ProtectedIdentity))
                {
                    person1ProtectedIdentity = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1ProtectedIdentity"));
                }
            }
        }

        private bool person1SexMale;
        public bool Person1SexMale
        {
            get
            {
                return person1SexMale;
            }
            set
            {
                if (!value.Equals(person1SexMale))
                {
                    person1SexMale = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1SexMale"));
                }
            }
        }

        private string coAddress;
        public string CoAddress
        {
            get
            {
                return coAddress;
            }
            set
            {
                if (value != null && !value.Equals(coAddress))
                {
                    coAddress = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("CoAddress"));
                }
            }
        }


        private string streetAddress;
        public string StreetAddress
        {
            get
            {
                return streetAddress;
            }
            set
            {
                if (!value.Equals(streetAddress))
                {
                    streetAddress = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("StreetAddress"));
                }
            }
        }

        private string zipCode;
        public string ZipCode
        {
            get
            {
                return zipCode;
            }
            set
            {
                if (!value.Equals(zipCode))
                {
                    zipCode = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("ZipCode"));
                }
            }
        }

        private string city;
        public string City
        {
            get
            {
                return city;
            }
            set
            {
                if (!value.Equals(city))
                {
                    city = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("City"));
                }
            }
        }

        private string country;
        public string Country
        {
            get
            {
                return country;
            }
            set
            {
                if (!value.Equals(country))
                {
                    country = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Country"));
                }
            }
        }


        #endregion

        #region Person2 properties

        private string person2FirstNames;
        public string Person2FirstNames
        {
            get
            {
                return person2FirstNames;
            }
            set
            {
                if (!value.Equals(person2FirstNames))
                {
                    person2FirstNames = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2FirstNames"));
                }
            }
        }

        private string person2LastName;
        public string Person2LastName
        {
            get
            {
                return person2LastName;
            }
            set
            {
                if (!value.Equals(person2LastName))
                {
                    person2LastName = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2LastName"));
                }
            }
        }

        private string person2PersonalNumber;
        public string Person2PersonalNumber
        {
            get
            {
                return person2PersonalNumber;
            }
            set
            {
                if (!value.Equals(person2PersonalNumber))
                {
                    person2PersonalNumber = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2PersonalNumber"));
                }
            }
        }

        private bool person2SwedishNationality;
        public bool Person2SwedishNationality
        {
            get
            {
                return person2SwedishNationality;
            }
            set
            {
                if (!value.Equals(person2SwedishNationality))
                {
                    person2SwedishNationality = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2SwedishNationality"));
                }
            }
        }

        private string person2Nationality;
        public string Person2Nationality
        {
            get
            {
                return person2Nationality;
            }
            set
            {
                if (!value.Equals(person2Nationality))
                {
                    person2Nationality = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2Nationality"));
                }
            }
        }

        private bool person2ProtectedIdentity;
        public bool Person2ProtectedIdentity
        {
            get
            {
                return person2ProtectedIdentity;
            }
            set
            {
                if (!value.Equals(person2ProtectedIdentity))
                {
                    person2ProtectedIdentity = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2ProtectedIdentity"));
                }
            }
        }

        private bool person2SexMale;
        public bool Person2SexMale
        {
            get
            {
                return person2SexMale;
            }
            set
            {
                if (!value.Equals(person2SexMale))
                {
                    person2SexMale = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person2SexMale"));
                }
            }
        }

        #endregion

        #region ContactPerson

        private bool person1IsContact;
        public bool Person1IsContact
        {
            get
            {
                return person1IsContact;
            }
            set
            {
                if (!value.Equals(person1IsContact))
                {
                    person1IsContact = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Person1IsContact"));
                }
            }
        }

        private string contactPersonFirstName;
        public string ContactPersonFirstName
        {
            get
            {
                return contactPersonFirstName;
            }
            set
            {
                if (!value.Equals(contactPersonFirstName))
                {
                    contactPersonFirstName = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("ContactPersonFirstName"));
                }
            }
        }

        private string contactPersonLastName;
        public string ContactPersonLastName
        {
            get
            {
                return contactPersonLastName;
            }
            set
            {
                if (!value.Equals(contactPersonLastName))
                {
                    contactPersonLastName = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("ContactPersonLastName"));
                }
            }
        }

        private string email;
        public string Email
        {
            get
            {
                return email;
            }
            set
            {
                if (value != null && !value.Equals(email))
                {
                    email = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Email"));
                }
            }
        }

        private string phone;
        public string Phone
        {
            get
            {
                return phone;
            }
            set
            {
                if (!value.Equals(phone))
                {
                    phone = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Phone"));
                }
            }
        }


        #endregion

        #endregion

        #region ErrorHandling and Validation

        public string this[string columnName]
        {
            get
            {
                if (errors.ContainsKey(columnName))
                    return errors[columnName];

                return null;
            }
            set
            {
                errors[columnName] = value;
            }
        }

        private void ClearError(string columnName)
        {
            if (errors.ContainsKey(columnName))
                errors.Remove(columnName);
        }

        private void Validate()
        {
            if (string.IsNullOrEmpty(Person1FirstNames))
            {
                this["Person1FirstNames"] = Resources.InvalidFirstName;
            }
            else
            {
                ClearError("Person1FirstNames");
            }

            if (string.IsNullOrEmpty(Person2FirstNames))
            {
                this["Person2FirstNames"] = Resources.InvalidFirstName;
            }
            else
            {
                ClearError("Person2FirstNames");
            }

            if (string.IsNullOrEmpty(Person1LastName))
            {
                this["Person1LastName"] = Resources.InvalidLastName;
            }
            else
            {
                ClearError("Person1LastName");
            }

            if (string.IsNullOrEmpty(Person2LastName))
            {
                this["Person2LastName"] = Resources.InvalidLastName;
            }
            else
            {
                ClearError("Person2LastName");
            }

            // Kontrollera epostadress *@a.b är giltig adress
            if(!string.IsNullOrEmpty(Email))
            {
                if (string.IsNullOrEmpty(Email))
                    this["Email"] = Resources.InvalidEmailAddress;
                else if (Email.Length > 200)
                    this["Email"] = Resources.EmailToLong;
                else if (EmailAddressValidationRule.IsValidEmail(Email))
                    ClearError("Email");
            }

            if (string.IsNullOrEmpty(Phone))
            {
                this["Phone"] = Resources.InvalidPhone;
            }
            else if (Phone.Length > 50)
            {
                this["Phone"] = Resources.PhoneToLong;
            }
            else
            {
                ClearError("Phone");
            }

            if (string.IsNullOrEmpty(ContactPersonFirstName))
            {
                this["ContactPersonFirstName"] = Resources.InvalidFirstName;
            }
            else if (ContactPersonFirstName.Length > 200)
            {
                this["ContactPersonFirstName"] = Resources.InvalidFirstName;
            }
            else
            {
                ClearError("ContactPersonFirstName");
            }

            if (string.IsNullOrEmpty(ContactPersonLastName))
            {
                this["ContactPersonLastName"] = Resources.InvalidLastName;
            }
            else if (ContactPersonLastName.Length > 70)
            {
                this["ContactPersonLastName"] = Resources.InvalidLastName;
            }
            else
            {
                ClearError("ContactPersonLastName");
            }

            // Kontrollera att man valt kön
            //if (Person1SexMale)
            //{
            //    this["Person1SexMale"] = Resources.InvalidLastName;
            //}
            //else
            //{
            //    ClearError("Person1SexMale");
            //}

            CheckAddressForValidity();
            CheckBirthdayNumberForValidity();
            CheckNationality();
        }

        private void CheckAddressForValidity()
        {
            if (!string.IsNullOrEmpty(StreetAddress) && StreetAddress.Length > 150)
            {
                this["StreetAddress"] = Resources.AddressToLong;
            }
            else
            {
                ClearError("StreetAddress");
            }

            if (!string.IsNullOrEmpty(CoAddress) && CoAddress.Length > 150)
            {
                this["CoAddress"] = Resources.CoAddressToLong;
            }
            else
            {
                ClearError("CoAddress");
            }

            if (!string.IsNullOrEmpty(ZipCode) && ZipCode.Length > 10)
            {
                this["ZipCode"] = Resources.ZipCodeToLong;
            }
            else
            {
                ClearError("ZipCode");
            }

            if (!string.IsNullOrEmpty(City) && City.Length > 150)
            {
                this["City"] = Resources.CityToLong;
            }
            else
            {
                ClearError("City");
            }

            if (!string.IsNullOrEmpty(Country) && Country.Length > 100)
            {
                this["Country"] = Resources.CountryToLong;
            }
            else
            {
                ClearError("Country");
            }

        }

        private void CheckBirthdayNumberForValidity()
        {
            string errorMessage;

            if (!Person1ProtectedIdentity)
            {
                if (PersonalNumberValidationRule.IsValidBirthdayNumber(Person1PersonalNumber, 
                    Person1SwedishNationality ? true : false, out errorMessage))
                {
                    ClearError("Person1PersonalNumber");
                }
                else
                {
                    this["Person1PersonalNumber"] = errorMessage;
                }
            }
            else
            {
                ClearError("Person1PersonalNumber");
            }

            if (!Person2ProtectedIdentity)
            {
                if (PersonalNumberValidationRule.IsValidBirthdayNumber(Person2PersonalNumber, 
                    Person2SwedishNationality ? true : false, out errorMessage))
                {
                    ClearError("Person2PersonalNumber");
                }
                else
                {
                    this["Person2PersonalNumber"] = errorMessage;
                }
            }
            else
            {
                ClearError("Person2PersonalNumber");
            }
        }

        private void CheckNationality()
        {
            if (!Person1SwedishNationality && 
                (string.IsNullOrEmpty(Person1Nationality) || Person1Nationality.Equals(Resources.NationalityInformationText)))
            {
                this["Person1Nationality"] = Resources.NationalityMustBeProvided;
            }
            else
            {
                ClearError("Person1Nationality");
            }

            if (!Person2SwedishNationality &&
                (string.IsNullOrEmpty(Person2Nationality) || Person2Nationality.Equals(Resources.NationalityInformationText)))
            {
                this["Person2Nationality"] = Resources.NationalityMustBeProvided;
            }
            else
            {
                ClearError("Person2Nationality");
            }
        }

        #endregion

        private void OnPropertyChangedEvent(object sender, PropertyChangedEventArgs e)
        {
            Validate();

            IsInChangeMode = true;

            SaveCommand.RaiseCanExecuteChanged();
        }

        private bool CanSave(object obj)
        {
            return errors.Count == 0;
        }

        private void Cancel(object obj)
        {
            OnCancelled(new DataEventArgs<CoupleDetailPresentationModel>(this));
        }

        private void Save(object obj)
        {
            if (CanSave(obj))
                OnSaved(new DataEventArgs<CoupleDetailPresentationModel>(this));
        }

        private void Add(object obj)
        {
            //eventAggregator.GetEvent<CoupleAddedEvent>().Publish(this);
            OnAdded(new DataEventArgs<CoupleDetailPresentationModel>(this));
        }

        private void Search(object obj)
        {
            //eventAggregator.GetEvent<CoupleAddedEvent>().Publish(this);
            OnSearch(new DataEventArgs<CoupleDetailPresentationModel>(this));
        }

        private void OnSaved(DataEventArgs<CoupleDetailPresentationModel> e)
        {
            var savedHandler = Saved;

            if (savedHandler != null)
            {
                savedHandler(this, e);
            }
        }

        private void OnAdded(DataEventArgs<CoupleDetailPresentationModel> e)
        {
            var addedHandler = Added;

            if (addedHandler != null)
                addedHandler(this, e);
        }

        private void OnSearch(DataEventArgs<CoupleDetailPresentationModel> e)
        {
            var searchHandler = Searched;

            if (searchHandler != null)
                searchHandler(this, e);
        }

        private void OnCancelled(DataEventArgs<CoupleDetailPresentationModel> e)
        {
            var cancelHandler = Cancelled;

            if (cancelHandler != null)
                cancelHandler(this, e);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IDataErrorInfo Members

        public string Error
        {
            get
            {
                // Inte implementerad, då vi inte använder denna, vi visar fel på varje kontroll istället.
                throw new NotImplementedException();
            }
        }

        #endregion
    }
}
